package main

import (
	"fmt"
	"math"
)

type Request struct {
	n      int
	replyc chan float64
}

type binOp func(int) float64

func run(op binOp, r *Request) {
	r.replyc <- op(r.n)
}

func server(op binOp, ch chan *Request, quit chan bool) {
	for {
		select {
		case r := <-ch:
			go run(op, r)
		case <-quit:
			return
		}
	}
}

func startServer(op binOp) (chan *Request, chan bool) {
	chanR := make(chan *Request)
	quit := make(chan bool)
	go server(op, chanR, quit)
	return chanR, quit
}

func main() {
	const N = 100
	var reqs [N]Request
	calcPi := func(n int) (res float64) {

		for i := 0; i < n; i++ {
			f := float64(i)
			sub := 4.0 * math.Pow(-1, f) / (2.0*f + 1.0)
			res += sub
		}
		return res
	}

	chanR, quit := startServer(calcPi)
	for i := 0; i < N; i++ {
		req := &reqs[i]
		req.n = i + N
		req.replyc = make(chan float64)
		chanR <- req
	}
	fmt.Println("print pi")
	for i := N - 1; i >= 0; i-- {
		fmt.Println(i+N, '-', <-reqs[i].replyc)
	}

	quit <- true

}
